package org.comanche.snaf.net.nio;

import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Collection;
import java.util.Iterator;

import org.comanche.snaf.core.polling.AbstractPollingProcess;

public class NioProcessor extends AbstractPollingProcess<NioSession> {
	
	///////////////////////////////////////////////////
	// member
	private Selector selector;
	
	///////////////////////////////////////////////////
	// inner class
	private class NioProcessSessions implements Iterator<NioSession> {

		Iterator<SelectionKey> keys;
		
		public NioProcessSessions(Collection<SelectionKey> keys){
			this.keys = keys.iterator();
		}
		
		
		public boolean hasNext() {
			return keys.hasNext();
		}

		public NioSession next() {
			SelectionKey selKey = keys.next();
			if (selKey.isValid()){
				return (NioSession)selKey.attachment();
			}
			return null;
		}

		public void remove() {
			keys.remove();
		}
		
	}
	
	///////////////////////////////////////////////////
	// protected field
	@Override
	protected void init() throws Exception{
		// get the system selector
		selector = Selector.open();
	}

	@Override
	protected int select(int timeout) throws Exception{
		if (timeout <= 0){
			return selector.select();
		} else {
			return selector.select(timeout);
		}
	}

	@Override
	protected void wakeup() {
		selector.wakeup();
	}

	@Override
	protected void bindInternal(NioSession session) throws Exception {
		SocketChannel ch = session.getChannel();
		
		if (ch != null){
			// add read key and attachment
			ch.register(selector, SelectionKey.OP_READ, session);
			ch.configureBlocking(false);
		}
		
	}

	@Override
	protected Iterator<NioSession> getSessions() {
		return new NioProcessSessions(selector.selectedKeys());
	}



}
